package org.example.uhy.domain.model.coupon;

import org.example.uhy.domain.model.base.TimeRange;
import org.example.uhy.supports.meta.ValueObject;

import java.math.BigDecimal;

/**
 * 卡券参数定义
 */
@ValueObject
public class CouponParameter {
    private String type; // 映射到具体的类，例如：DiscountCoupon、VoucherCoupon、TimesCoupon
    // 抵扣金额的消费额度
    private BigDecimal quota;
    // 抵扣金额
    private BigDecimal decrease;
    // 折扣
    private BigDecimal discount;
    // 次数
    private Integer counting;

    private CouponParameter() {
    }

    private CouponParameter(String type) {
        this.setType(type);
    }

    public Coupon createCoupon(CouponId couponId, CouponArchiveId archiveId, String couponName, TimeRange effectiveTime) {
        Coupon coupon = null;
        switch (this.type) {
            case DiscountCoupon.TYPE:
                coupon = new DiscountCoupon(couponId, archiveId, couponName, effectiveTime, this);
                break;
            case QuotaDiscountCoupon.TYPE:
                coupon = new QuotaDiscountCoupon(couponId, archiveId, couponName, effectiveTime, this);
                break;
            case CountingCoupon.TYPE:
                coupon = new CountingCoupon(couponId, archiveId, couponName, effectiveTime, this);
                break;
            case VoucherCoupon.TYPE:
                coupon = new VoucherCoupon(couponId, archiveId, couponName, effectiveTime, this);
                break;
        }
        if (coupon == null) {
            throw new IllegalArgumentException("unsupported coupon type");
        }
        return coupon;
    }

    public static CouponParameter ofParameters(String type, BigDecimal quota, BigDecimal decrease, BigDecimal discount, Integer counting) {
        CouponParameter parameter = null;
        switch (type) {
            case DiscountCoupon.TYPE:
                parameter = ofDiscount(discount);
                break;
            case QuotaDiscountCoupon.TYPE:
                parameter = ofQuotaDiscount(quota, discount);
                break;
            case CountingCoupon.TYPE:
                parameter = ofCounting(counting);
                break;
            case VoucherCoupon.TYPE:
                parameter = ofVoucher(quota, decrease);
                break;
        }
        return parameter;
    }

    public static CouponParameter ofDiscount(BigDecimal discount) {
        CouponParameter parameter = new CouponParameter(DiscountCoupon.TYPE);
        parameter.withDiscount(discount);
        return parameter;
    }

    public static CouponParameter ofQuotaDiscount(BigDecimal quota, BigDecimal discount) {
        CouponParameter parameter = new CouponParameter(QuotaDiscountCoupon.TYPE);
        parameter.withQuota(quota);
        parameter.withDiscount(discount);
        return parameter;
    }

    public static CouponParameter ofCounting(Integer counting) {
        CouponParameter parameter = new CouponParameter(CountingCoupon.TYPE);
        parameter.withCounting(counting);
        return parameter;
    }

    public static CouponParameter ofVoucher(BigDecimal quota, BigDecimal decrease) {
        CouponParameter parameter = new CouponParameter(VoucherCoupon.TYPE);
        parameter.withQuota(quota);
        parameter.withDecrease(decrease);
        parameter.checkQuotaAndDecrease();
        return parameter;
    }

    private void withQuota(BigDecimal quota) {
        if (quota == null || quota.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("请输入正确的消费金额额度");
        }
        this.quota = quota;
    }

    private void withCounting(Integer counting) {
        if (counting == null || counting <= 0) {
            throw new IllegalArgumentException("请输入正确的可用次数");
        }
        this.counting = counting;
    }

    private void withDiscount(BigDecimal discount) {
        if (discount == null || discount.compareTo(BigDecimal.ZERO) <= 0 || discount.compareTo(BigDecimal.ONE) >= 0) {
            throw new IllegalArgumentException("请输入正确的折扣值");
        }
        this.discount = discount;
    }

    private void withDecrease(BigDecimal decrease) {
        if (decrease == null || decrease.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("请输入正确的抵扣金额");
        }
        this.decrease = decrease;
    }

    public String getType() {
        return type;
    }

    private void setType(String type) {
        if (type == null || type.length() == 0) {
            throw new IllegalArgumentException("请输入卡券类型");
        }
        this.type = type;
    }

    public BigDecimal getQuota() {
        return quota;
    }

    private void setQuota(BigDecimal quota) {
        this.quota = quota;
    }

    public BigDecimal getDecrease() {
        return decrease;
    }


    private void setDecrease(BigDecimal decrease) {
        this.decrease = decrease;
    }

    public Integer getCounting() {
        return counting;
    }

    public void decreaseCounting(int count) {
        if (counting < count) {
            throw new IllegalArgumentException("扣减次数大于可用次数");
        }
        this.counting -= count;
    }

    private void setCounting(Integer counting) {
        this.counting = counting;
    }

    public BigDecimal getDiscount() {
        return discount;
    }

    private void setDiscount(BigDecimal discount) {
        this.discount = discount;
    }

    private void checkQuotaAndDecrease() {
        if (this.quota.compareTo(this.decrease) <= 0) {
            throw new IllegalArgumentException("抵扣金额必须小于消费额度");
        }
    }
}